Amazon ECSハンズオンで構築したRuby on RailsアプリをCI/CD経由でデプロイしてみた

Amazon ECSハンズオンで構築したRuby on RailsアプリをCI/CD経由でデプロイしてみた

ハンズオンで構築したAmazon ECS管理下のRuby ob Rails環境に、AWSの CodeシリーズのCI/CD環境を整備します。内容はハンズオンほぼそのままですが、Codeシリーズの各コンポーネントの役割をまとめながら整理していきます。

Clock Icon2024.6.19

Amazon ECSで管理しているアプリのCI/CD環境を整えたい

おのやんです。

Amazon ECS(以下、ECS)で管理しているアプリのCI/CD環境を整えたいと思ったことはありませんか?私はあります。

AWSでは、比較的簡単な構成を自差しに触りながら構築して、AWSサービスを学べるハンズオンがあります。今回私がECSを学習する上でも、こちらの日本語ハンズオンを参考にしました。このハンズオンでは、Ruby on Rails(以下、Rails)アプリケーションをコンテナ化してECSで管理したのち、発展内容としてAWSのCodeシリーズを使ったCI/CD環境を整備していきます。

RailsアプリをECSで管理するまでの内容は、こちらの記事でまとめていますので、今回の内容はこちらの記事に続けて書く形にないます。

ということで、今回はハンズオンの内容を進める形で、具体的な構成図とともに、CI/CD環境の整備をまとめていきたいと思います。

目指す構成

今回目指す構成はこちらになります。右側のECS環境は、さきほど共有した別記事にてまとめています。今回は左側のAWS CodePipeline(以下、CodePipeline)を作成していき、その中でAWS CodeCommit(以下、CodeCommit)を用いたソースコード管理やAWS CodeBuild(以下、CodeBuild)を用いたコンテナイメージのビルド、AWS CodeDeploy(以下、CodeDeploy)を用いたアプリケーションのデプロイを設定してきます。

ビルド設定ファイルの設定

ここからの流れでは、基本的にハンズオンの流れに従っていきます。また補足情報なども適宜付け加えながらまとてめていきます。

今回のハンズオンでは、AWS CLIを使ってCodeCommitのリポジトリを作成します。

Cloud9環境のコンソールで以下のコマンドを実行して、CodeCommitリポジトリを作成してきます。

$ aws codecommit create-repository --repository-name rails-app

正常に実行されると、このように CodeCommit上でリポジトリを確認できるようになります。

続いて、このCodeCommitリポジトリをCloud9環境の~/environment/handsonディレクトリと連携します。

cd ~/environment/handson
git init -b main
git remote add origin codecommit::ap-northeast-1://rails-app

これらGit関係の設定ができましたら、CodeBuildでビルドするための設定ファイルを作成します。ハンズオンの流れで、Cloud9環境に~/environment/handson/のディレクトリが作成されていると思いますので、この直下にbuildspec.yamlimagedefinitions.jsonを作成します。なおハンズオンにはimagedefinitions.jsonのサンプルコードは掲載されていませんので、いい感じに作成します。

version: 0.2

env:
  variables:
    CONTAINER_NAME: "rails-app"

phases:
  pre_build:
    commands:
      # AWS アカウント ID を取得する
      - AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
      # リポジトリの URI を設定する
      - REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${CONTAINER_NAME}
      # コミット ID をもとに、コンテナイメージのタグを生成する
      - IMAGE_TAG=$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | cut -c 1-7)
      # ECR にログインする
      - aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com

  build:
    commands:
      # コンテナイメージをビルドする
      - docker build -t ${REPOSITORY_URI}:latest .
      # 生成したイメージタグを付与する
      - docker tag ${REPOSITORY_URI}:latest ${REPOSITORY_URI}:${IMAGE_TAG}

  post_build:
    commands:
      # ビルドしたコンテナイメージを ECR にプッシュする
      - docker push ${REPOSITORY_URI}:${IMAGE_TAG}
      # "コンテナの名前" と "コンテナイメージの URI" を imagedefinitions.json に書き込む
      - printf '[{"name":"%s","imageUri":"%s"}]' ${CONTAINER_NAME} ${REPOSITORY_URI}:${IMAGE_TAG}  > imagedefinitions.json

artifacts:
  files:
    - imagedefinitions.json

[
  {
    "name": "rails-app",
    "imageUri": "<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/rails-app:latest"
  }
]

これらのファイルを作成したら、 Cloud9環境でGitを設定して、~/environment/handson/直下のファイルをCodeCommitにプッシュします。

git add .
git commit -m "Initial commit"
git push origin main

正常にプッシュできると、こちらの用にCodeCommitで各ファイルを管理できるようになります。

Codeipelineでパイプラインの作成

続いて、Ci/CDで用いるパイプラインを作成していきます。具体的には、CodePipelineを作成する段階でCodeBuild、CodeDeployの設定をまとめて行うイメージです。

その中でも、まずはCodePipelineのパイプラインを作成していきます。

CodePipelineのコンソール画面に入り、「パイプラインを作成する」ボタンを押下します。

パイプライン名はecs-test-pipelineとします。またハンズオンの内容にはありませんが、ハンズオン作成時からアップデートが入り、パイプラインタイプ・実行モードの項目がパイプライン設定画面に追加されています。パイプラインタイプはV2、実行モードはキュー(パイプラインタイプV2が必須)を選択します。サービスロールは「新しいサービスロール」を選択します。こちらを選択することで、ロール名にもある通りAWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipelineというIAMロールが自動で作成・適用されます。

CodePipelineのV1とV2は、基本構造が同じであり、V2を選択することで追加のパラメータを設定することができます。今回はハンズオンの内容に影響はありませんので、できることが多いV2を選択していて問題ありません。

またAWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipelineロールにはAWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipelineポリシーがアタッチされており、その内容は以下のようになっています。CodeシリーズやEC2, ECS, ALBなど、さまざまなリソースにアクセスできるようCodePipelineに許可を与えています。

続いて、ソースとなるコードを追加します。ソースプロバイダは「AWS CodeCommit」、リポジトリ名は「rails-app」、ブランチ名は「main」を選択します。

続いて、ビルドに関する設定を行っていきます。構成図でいうと、CodeCommit内のコード変更を検知して、コンテナイメージをビルドする部分です

プロバイダーは「AWS CodeBuild」で、リージョンは「アジアパシフィック(東京)」を選択します。ここから、プロジェクト名の「プロジェクトを作成する」を押下します。

すると、Webブラウザの別ウィンドウが開き、ビルドプロジェクトの設定画面が表示されます。ここから、ビルドに関する詳細な設定を進めていきます。なお、ここはハンズオン作成当時からコンソール画面が大幅に変わっていますので、注意してください。

まず、ビルドプロジェクトの名前はecs-test-projectにしておきます。

続いて、ビルドを実行する環境について設定を進めていきます。それぞれの項目について、「オンデマンド」「マネージド型イメージ」「ECS」を選択していきます。また、オペレーティングシステムはAmazon Linux、ランタイムは「Standard」、イメージは「aws/codebuild/amazonlinux2-x86_64-standard:5.0」、イメージのバージョンは最近のイメージを使用するよう設定します。またサービスロールについては「新しいサービスロール」を選択し、新規でIAMロールが作成されるようにします。

そしてここの「追加設定」トグルを開き、特権付与の部分にチェックを入れます。

続いて、Buildspecに関する設定です。さきほどbuildspec.yamlを作成していますので、「buildspec.yamlファイルを使用する」を選択し、buildspec.yamlのファイル名を入力しておきます。

ログについては、CloudWatch Logsにチェックを入れておきます。

こちらを設定し終わったら、「CodePipelineに進む」を押下します。すると、こちらのウィンドウが自動的に閉じて、ビルドステージ設定画面に戻ります。「プロジェクト名」をみてみると、ecs-test-projectが追加されているのがわかります。

最後にデプロイに関する設定を行います。構成図でいうと、ECRからコンテナイメージを取得してECS管理のFargateにデプロイする部分です。

それぞれの項目について、デプロイプロバイダーは「Amazon ECS」、「リージョンはアジアパシフィク」、クラスターはecs-test-cluster、サービスはecs-test-fargate-service、イメージ定義ファイルはimagedefinitions.jsonを選択します。

以上を入力できたら、パイプラインを作成します。なお、このままではIAMロールに必要な権限が足りない状態ですので、ビルドに失敗します。ですので、CodeBuildのビルドプロジェクトを設定した時に作成されたcodebuild-ecs-test-project-service-roleに、田 AmazonEC2 ContainerRegistryFullAccessのマネージドポリシーを追加しておきます。

これで、再度ビルドを実行すると、今回は問題なく通ることが確認できます

コードの変更をパイプライン経由で反映・デプロイ

それでは、ハンズオンにならって実際にコードを変更し、デプロイしていきたいと思います。Cloud9上でDockerfileを以下のように編集します。

# ruby:3.2.1 というベースイメージを取得する
FROM public.ecr.aws/docker/library/ruby:3.2.1

# 必要なパッケージ群を取得する
RUN apt-get update -qq && \
    apt-get install -y nodejs postgresql-client npm && \
    rm -rf /var/lib/apt/lists/\*

# ローカルにあるファイルをコンテナイメージ内にコピーする
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile

# Rails アプリケーションを作成する
RUN bundle install && \
    rails new . -O && \
    sed -i -e "52a\  config.hosts.clear\n  config.web_console.allowed_ips = '0.0.0.0/0'\n  config.action_dispatch.default_headers.delete('X-Frame-Options')" config/environments/development.rb

# welcome ページの背景色を blue にする
RUN sed -i -e "s/background-color: #F0E7E9;/background-color: #99CCFF;/g" /usr/local/bundle/gems/railties-7.0.4/lib/rails/templates/rails/welcome/index.html.erb

# Rails を 3000 番ポートで起動する
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0", "-p", "3000"]

こちらの変更をcommitし、CodeCommitにプッシュします。

$ git add Dockerfile
$ git commit -m "Change background color"
$ git push origin main

すると、CodeCommitのプッシュをEvent Bridgeで検知して、CodePipelineが開始します。CodeCommitのソースコードを元にCodeBuildでコンテナイメージが作成され、このイメージを元にECS管理のFargate上にデプロイされます。

Fargate用のALBのドメインにアクセスすると、Railsの背景色が青色になったことを確認できました。

CodePipelineのパイプラインの中で、ビルドやデプロイなどを設定する

AWSのマネジメントコンソールを操作して、実際にCodeシリーズを設定することで、それぞれのサービスがどのように動作するのかを理解することができました。

ハンズオンと実際のコンソールで多少の違いはありましたが、AWSサービスを用いたCI/CDを学べる資料としても、ECSハンズオンは非常に効果的だと感じました。みなさんもぜひECSハンズオンをやってみてください。では!

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.